package com.itheima.leetcode.od.b.sort;

import java.util.Arrays;
import java.util.HashMap;
import java.util.stream.Collectors;

/**
 * (B卷,100分)- 比赛（Java & JS & Python）
 * <p>
 * 题目描述
 * <p>
 * 一个有N个选手参加比赛，选手编号为1~N（3<=N<=100），有M（3<=M<=10）个评委对选手进行打分。
 * <p>
 * 打分规则为每个评委对选手打分，最高分10分，最低分1分。
 * <p>
 * 请计算得分最多的3位选手的编号。
 * <p>
 * 如果得分相同，则得分高分值最多的选手排名靠前
 * <p>
 * (10分数量相同，则比较9分的数量，以此类推，用例中不会出现多个选手得分完全相同的情况)。
 * <p>
 * 输入描述
 * <p>
 * 第一行为半角逗号分割的两个正整数，第一个数字表示M（3<=M<=10）个评委，第二个数字表示N（3<=N<=100）个选手。
 * <p>
 * 第2到M+1行是半角逗号分割的整数序列，表示评委为每个选手的打分，0号下标数字表示1号选手分数，1号下标数字表示2号选手分数，依次类推。
 * <p>
 * 输出描述
 * <p>
 * 选手前3名的编号。
 * <p>
 * 注：若输入为异常，输出-1，如M、N、打分不在范围内。
 * <p>
 * 用例
 * <p>
 * 输入	4,5
 * <p>
 * 10,6,9,7,6
 * <p>
 * 9,10,6,7,5
 * <p>
 * 8,10,6,5,10
 * <p>
 * 9,10,8,4,9
 * <p>
 * 输出	2,1,5
 * <p>
 * 说明
 * <p>
 * 第一行代表有4个评委，5个选手参加比赛
 * <p>
 * 矩阵代表是4*5，每个数字是选手的编号，每一行代表一个评委对选手的打分排序，
 * <p>
 * 2号选手得分36分排第1，1号选手36分排第2，5号选手30分(2号10分值有3个，1号10分值只有1个，所以2号排第一)
 * <p>
 * 输入	2,5
 * <p>
 * 7,3,5,4,2
 * <p>
 * 8,5,4,4,3
 * <p>
 * 输出	-1
 * <p>
 * 说明	只有2个评委，要求最少为3个评委
 * <p>
 * 输入	4,2
 * <p>
 * 8,5
 * <p>
 * 5,6
 * <p>
 * 10,4
 * <p>
 * 8,9
 * <p>
 * 输出	-1
 * <p>
 * 说明	只有2名选手参加，要求最少为3名
 * <p>
 * 输入	4,5
 * <p>
 * 11,6,9,7,8
 * <p>
 * 9,10,6,7,8
 * <p>
 * 8,10,6,9,7
 * <p>
 * 9,10,8,6,7
 * <p>
 * 输出	-1
 * <p>
 * 说明	第一个评委给第一个选手打分11，无效分数
 * <p>
 * 题目解析
 * <p>
 * 考察数组排序，主要难点在于下面逻辑的设计
 * <p>
 * 如果得分相同，则得分高分值最多的选手排名靠前
 * <p>
 * 我这里直接将选手分数降序排序后，join('')为字符串数值，高分多的选手该字符串数值越大
 */
public class Competition {
    // 输入获取
    public static void main(String[] args) {
        /*// 将输入分隔符设置为“,”或者换行
        Scanner sc = new Scanner(System.in).useDelimiter("[,\n]");

        int m = sc.nextInt();
        int n = sc.nextInt();

        int[][] scores = new int[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                scores[i][j] = sc.nextInt();
            }
        }*/

        int m = 4;
        int n = 5;

        int[][] scores = Arrays.stream("10,6,9,7,6\n9,10,6,7,5\n8,10,6,5,10\n9,10,8,4,9".split("\n"))
                .map(s -> Arrays.stream(s.split(","))
                        .mapToInt(Integer::parseInt)
                        .toArray())
                .toArray(int[][]::new);

        System.out.println(getResult(m, n, scores));
    }

    // 算法入口
    public static String getResult(int m, int n, int[][] scores) {
        if (m < 3 || m > 10 || n < 3 || n > 100) {
            return "-1";
        }

        HashMap<Integer, Integer[]> players = new HashMap<>();

        for (int j = 0; j < n; j++) { // 列
            Integer[] player = new Integer[m];
            for (int i = 0; i < m; i++) { // 行
                if (scores[i][j] > 10 || scores[i][j] < 1) {
                    return "-1"; // 队员得分1~10合法，否则不合法
                }
                player[i] = scores[i][j];
            }
            Arrays.sort(player, (a, b) -> b - a); // 将每个队员的得分降序
            players.put(j, player);
        }

        return players.entrySet().stream()
                .sorted(
                        (a, b) -> {
                            Integer[] playerA = a.getValue();
                            Integer[] playerB = b.getValue();

                            int sumA = sum(playerA);
                            int sumB = sum(playerB);

                            if (sumA != sumB) { // 按总分降序
                                return sumB - sumA;
                            }

                            for (int i = 0; i < m; i++) {
                                if (playerA[i] == playerB[i]) {
                                    continue;
                                }
                                return playerB[i] - playerA[i]; // 得分高分值最多的选手排名靠前
                            }

                            return 0;
                        })
                .limit(3)
                .map(p -> String.valueOf(p.getKey() + 1))
                .collect(Collectors.joining(","));
    }

    public static int sum(Integer[] arr) {
        return Arrays.stream(arr)
                .reduce(Integer::sum)
                .orElse(0);
    }
}